
#ifndef RTHTTPAUTHENTICATOR_H
#define RTHTTPAUTHENTICATOR_H

#include "RtReferenceControl.h"

class IRtChannelHttpClient;

class IRtHttpAuthenticator : public CRtReferenceControlSingleThread
{
public:
	virtual CRtString GenerateCredentials(
		IRtChannelHttpClient *aChannel, 
		LPCSTR aChallenge, 
		LPCSTR aUsername, 
		LPCSTR aPassword) = 0;

	virtual BOOL AreCredentialsReusable() = 0;

	virtual BOOL HaveAuthenticateComplete() = 0;

	virtual BOOL AllowFirstTryWithoutUserName() = 0;

	virtual LPCSTR GetAuthenticateScheme() = 0;

	virtual DWORD GetAuthStep() = 0;

	static IRtHttpAuthenticator* GetAuthenticatorFromScheme(
		const CRtString &aScheme);

	static CRtString GetSchemeFromChallenge(
		const CRtString &aChallenge);

protected:
	virtual ~IRtHttpAuthenticator();
};

class CRtHttpAuthSteps : public IRtHttpAuthenticator
{
public:
	CRtHttpAuthSteps(DWORD aSteps);
	virtual ~CRtHttpAuthSteps();
	
	virtual BOOL HaveAuthenticateComplete();

	virtual DWORD GetAuthStep();

	// implement template pattern
	virtual CRtString GenerateCredentials(
		IRtChannelHttpClient *aChannel, 
		LPCSTR aChallenge, 
		LPCSTR aUsername, 
		LPCSTR aPassword);

	virtual CRtString do_GenerateCredentials(
		IRtChannelHttpClient *aChannel, 
		LPCSTR aChallenge, 
		LPCSTR aUsername, 
		LPCSTR aPassword) = 0;

protected:
	DWORD m_dwAuthSteps;
	DWORD m_dwAuthStepsMax;
};

class CRtHttpBasicAuth : public CRtHttpAuthSteps
{
public:
	CRtHttpBasicAuth();
	virtual ~CRtHttpBasicAuth();

	virtual CRtString do_GenerateCredentials(IRtChannelHttpClient *aChannel, LPCSTR aChallenge, 
		LPCSTR aUsername, LPCSTR aPassword);

	virtual BOOL AreCredentialsReusable();
	virtual BOOL AllowFirstTryWithoutUserName();
	virtual LPCSTR GetAuthenticateScheme();

	static const char *s_pszBasicAuth;
};

class CRtHttpDigestAuth : public CRtHttpAuthSteps
{
public:
	CRtHttpDigestAuth();
	virtual ~CRtHttpDigestAuth();

	virtual CRtString do_GenerateCredentials(IRtChannelHttpClient *aChannel, LPCSTR aChallenge, 
		LPCSTR aUsername, LPCSTR aPassword);

	virtual BOOL AreCredentialsReusable();
	virtual BOOL AllowFirstTryWithoutUserName();
	virtual LPCSTR GetAuthenticateScheme();

	static const char *s_pszDigestAuth;

private:
	BOOL ParseChallenge(const char *aChallenge, CRtString &strRealm, 
		CRtString &strNonce, CRtString &strOpaque, WORD &nAlgorithm, WORD &nQop);
	
	DWORD m_dwExtra;
};

#endif // !RTHTTPAUTHENTICATOR_H
